﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using DomainModel;
using Repository.Abstract;
using Services.Abstract;

namespace Services.Concrete
{
    public class LessonService : Service<Lesson>, ILessonService
    {
        private readonly ILessonRepository _lessonRepository;

        public LessonService(ILessonRepository lessonRepository, IPrincipal currentUser,
                             IPermissionService permissionService)
            : base(lessonRepository, currentUser, permissionService)
        {
            _lessonRepository = lessonRepository;
        }

        #region ILessonService Members

        public Lesson GetLesson(DateTime date, User student, TimetableUnit timetableUnit)
        {
            if (student == null)
                throw new ArgumentNullException("student");

            if (timetableUnit == null)
                throw new ArgumentNullException("timetableUnit");

            return _lessonRepository.GetLessonByDateStudentTimetableUnit(date, student, timetableUnit);
        }

        public List<Lesson> GetLessons(Group group)
        {
            if (group == null)
                throw new ArgumentNullException("group");

            return _lessonRepository.GetLessonsByGroup(group).ToList();
        }

        public List<Lesson> GetLessons(Group group, Subject subject)
        {
            if (group == null)
                throw new ArgumentNullException("group");

            if (subject == null)
                throw new ArgumentNullException("subject");

            return _lessonRepository.GetLessonsByGroupAndSubject(group, subject).ToList();
        }

        public List<Lesson> GetLessons(StudySemester semester, Group group, Subject subject)
        {
            if (semester == null)
                throw new ArgumentNullException("semester");

            if (group == null)
                throw new ArgumentNullException("group");

            if (subject == null)
                throw new ArgumentNullException("subject");

            return _lessonRepository.GetLessonsBySemesterAndGroupAndSubject(semester, group, subject).ToList();
        }

        public int GetMissedLessonsNumber(StudySemester semester, User student, Subject subject)
        {
            if (semester == null) 
                throw new ArgumentNullException("semester");
            if (student == null) 
                throw new ArgumentNullException("student");
            if (subject == null) 
                throw new ArgumentNullException("subject");

            return _lessonRepository.GetMissedLessonsNumber(semester, student, subject);
        }

        public double GetAvgBall(StudySemester semester, User student, Subject subject)
        {
            if (semester == null)
                throw new ArgumentNullException("semester");
            if (student == null)
                throw new ArgumentNullException("student");
            if (subject == null)
                throw new ArgumentNullException("subject");

            return _lessonRepository.GetAvgBall(semester, student, subject);
        }

        public List<Lesson> GetLessons(StudySemester semester, User student, DateTime beginDate, DateTime endDate)
        {
            if (semester == null) 
                throw new ArgumentNullException("semester");

            if (student == null)
                throw new ArgumentNullException("student");

            if (beginDate > endDate)
                throw new Exception("Вермя начала поиска не может быть больше времени конца поиска.");

            if (student.Role != Role.Student)
                throw new Exception("Пользователь для поиска не студент.");

            if (beginDate < semester.BeginDate)
                throw new Exception("Время начала поиска меньше времени начала семестра.");

            if (beginDate > semester.EndDate)
                throw new Exception("Время начала поиска больше времени окончания семестра.");

            if (endDate < semester.BeginDate)
                throw new Exception("Время окончания поиска меньше времени начала семестра.");

            if (endDate > semester.EndDate)
                throw new Exception("Время окончания поиска больше времени окончания семестра.");

            return _lessonRepository.GetLessonsBySemesterAndStudentAndDateRange(semester, student, beginDate, endDate).ToList();
        }

        public List<Lesson> GetLessons(User student, DateTime date)
        {
            if (student == null)
                throw new ArgumentNullException("student");

            if (student.Role != Role.Student)
                throw new Exception("Пользователь для поиска не студент.");

            return _lessonRepository.GetLessonsByStudentAndDate(student, date).ToList();
        }

        public new void SaveOrUpdate(Lesson lesson)
        {
            if (lesson == null)
                throw new ArgumentNullException("lesson");

            if (lesson.Date > DateTime.Now)
                throw new Exception("Время урока больше текущего времени.");

            if (lesson.Student == null)
                throw new Exception("Не указано для какого студента добавлять урок.");

            if (lesson.TimetableUnit == null)
                throw new Exception("Не указано для какой пары в какое время добавлять урок.");

            if (lesson.Id > 0)
            {
                if (!PermissionService.CanChangeMark(lesson))
                    throw new Exception("Недостаточно прав чтобы изменять оценку.");
            }

            base.SaveOrUpdate(lesson);
        }

        #endregion
    }
}